package com.alan.netty.nio.buffers;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.ReadOnlyBufferException;

/**
 * ByteBuffer duplicate()
 * ByteBuffer slice()
 * ByteBuffer asReadOnlyBuffer()
 * CharBuffer asCharBuffer()
 * DoubleBuffer asDoubleBuffer()
 * FloatBuffer asFloatBuffer()
 * IntBuffer asIntBuffer()
 * LongBuffer asLongBuffer()
 * ShortBuffer asShortBuffer()
 * @author weiBin
 * @date 2018/11/7
 */
public class BufferCopy {
    public static void main(String[] args) {
        asReadOnlyBuffer();
    }
    /**
     * asReadOnlyBuffer()方法的功能与duplicate()方法相似 一样的结构 但只能读取 不能进行修改 无法调用put compact
     * 可以调用isReadonly 来判断是否为只读的 只读缓存区 进行 slice duplicate 拷贝也是只读
     * */
    public static void asReadOnlyBuffer() {
        CharBuffer buffer = CharBuffer.allocate(8);
        buffer.put('H');
        buffer.put('E');
        buffer.put('L');
        buffer.put('i');
        buffer.put('o');
        buffer.flip();
        printBuffer(buffer);
        CharBuffer readOnlyBuffer = buffer.asReadOnlyBuffer();
        while (readOnlyBuffer.hasRemaining()){
            System.out.println(readOnlyBuffer.get());
        }
        printBuffer(readOnlyBuffer);
        System.out.println(readOnlyBuffer.isReadOnly());
        try {
            readOnlyBuffer.compact();
        }catch (ReadOnlyBufferException e){
            System.err.println(e.getLocalizedMessage());
        }
        CharBuffer dupBuffer = readOnlyBuffer.duplicate();
        System.out.println(dupBuffer.isReadOnly());
    }

    /**
     * duplicate() 方法用于创建一个与原始缓冲区共享内容的新缓冲区。
     * 新缓冲区的position，limit，mark和capacity都初始化为原始缓冲区的索引值，
     * 然而，它们的这些值是相互独立的。
     */
    public static void duplicate() {
        CharBuffer buffer = CharBuffer.allocate(8);
        buffer.put('H');
        buffer.put('E');
        buffer.put('L');
        buffer.put('i');
        buffer.put('o');
        buffer.flip();
        printBuffer(buffer);
        CharBuffer dupBuffer = buffer.duplicate();
        printBuffer(dupBuffer);
        for (int i = dupBuffer.position(); i < dupBuffer.limit(); i++) {
            dupBuffer.put(i, String.valueOf(i).charAt(0));
        }
        printBuffer(dupBuffer);
        buffer.clear();
        printBuffer(buffer);
        printBuffer(dupBuffer);
        dupBuffer.clear();
        printBuffer(dupBuffer);
        for (int i = 0; i < dupBuffer.limit(); i++) {
            System.out.println(dupBuffer.get());
        }
    }

    /**
     * slice()方法用于创建一个共享了原始缓冲区子序列的新缓冲区。
     * 新缓冲区的position值是0，而其limit和capacity的值都等于原始缓冲区的limit和position的差值。
     * slice()方法将新缓冲区数组的offset值设置为原始缓冲区的position值
     * 但调用array方法 还是能返回原始缓冲区整个数组
     */
    public static void slice() {
        ByteBuffer buffer = ByteBuffer.allocate(10);
        for (int i = 0; i < buffer.capacity(); i++) {
            buffer.put((byte) i);
        }
        buffer.position(3).limit(5);
        ByteBuffer slice = buffer.slice();
        printBuffer(slice);
        for (int i = 0; i < slice.capacity(); i++) {
            slice.put(i, (byte) (slice.get(i) * 11));
        }
        printBuffer(buffer);
        while (buffer.hasRemaining()) {
            System.out.println(buffer.get());
        }
        byte[] array = slice.array();
        for (byte b : array) {
            System.out.println(b);
        }
    }

    private static void printBuffer(Buffer buffer) {
        System.out.println("[limit=" + buffer.limit()
                + ", position = " + buffer.position()
                + ", capacity = " + buffer.capacity()
                + ",remaining =" + buffer.remaining()
                + ", array = " + buffer.toString() + "]");
    }
}
